package com.glsc.ngateway.platform.service.costallocation;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.github.pagehelper.util.StringUtil;
import com.glsc.ngateway.common.api.common.utils.PageUtil;
import com.glsc.ngateway.common.api.ldap.dto.LdapEhrEmpDto;
import com.glsc.ngateway.common.api.ldap.feign.IFeignLdapService;
import com.glsc.ngateway.common.api.ldap.resp.LdapResponse;
import com.glsc.ngateway.common.api.platform.dto.user.PlatformUserDto;
import com.glsc.ngateway.common.api.shortmsg.bo.MessageGenericVo;
import com.glsc.ngateway.common.api.shortmsg.feign.IFeignShortmsgService;
import com.glsc.ngateway.common.base.domain.mysql.gateway.other.SystemConfig;
import com.glsc.ngateway.common.base.domain.mysql.gateway.platform.it.ItCloudDevice;
import com.glsc.ngateway.common.base.domain.mysql.gateway.platform.it.ItServerDevice;
import com.glsc.ngateway.common.base.domain.mysql.gateway.platform.it.ItVirtualDevice;
import com.glsc.ngateway.common.base.exception.PlatformException;
import com.glsc.ngateway.platform.aspect.UserCache;
import com.glsc.ngateway.platform.domain.costallocation.*;
import com.glsc.ngateway.platform.dto.*;
import com.glsc.ngateway.platform.repo.costallocation.*;
import com.glsc.ngateway.platform.service.SystemConfigService;
import com.glsc.ngateway.platform.utils.AssertOverride;
import com.glsc.ngateway.platform.utils.SpecificationUtil;
import com.glsc.ngateway.platform.utils.StringUtils;
import com.glsc.ngateway.platform.utils.report.ReportFileConfigEnum;
import com.glsc.ngateway.platform.utils.report.ReportFileUtil;
import com.glsc.ngateway.platform.utils.report.ReportUploadContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static com.glsc.ngateway.common.api.common.enums.Constant.*;

/**
 * @author guoj
 * @description: 应用详情信息
 * @date 2024/8/7 14:39
 */
@Service
public class IpInfoService {
    private static Logger logger = LoggerFactory.getLogger(IpInfoService.class);

    @Autowired
    private UserCache userCache;
    @Autowired
    private HttpServletRequest request;
    @Autowired
    private IpInfoRepo ipInfoRepo;
    @Resource
    IFeignLdapService feignLdapService;
    @Autowired
    private IpDetailInfoRepo ipDetailInfoRepo;
    @Autowired
    private IpDetailInfoService ipDetailInfoService;
    @Autowired
    private SystemComponentCategoryRepo systemComponentCategoryRepo;
    @Autowired
    private BusiSystemInfoRepo busiSystemInfoRepo;
    @Autowired
    private HisBusiSystemInfoRepo hisBusiSystemInfoRepo;
    @Autowired
    private HisIpInfoService hisIpInfoService;
    @Autowired
    private HisIpInfoRepo hisIpInfoRepo;
    @Autowired
    private HisIpDetailInfoRepo hisIpDetailInfoRepo;
    @Resource
    private SystemConfigService configService;
    @Resource
    private IFeignShortmsgService shortmsgService;

    /**
     * 保存数据
     * @param ipInfoDto
     */
    @Transactional
    public void saveOrUpdateCurrAndHistory(IpInfoDto ipInfoDto) {
        check4Save(ipInfoDto);
        PlatformUserDto user = userCache.get(request);
        String username = user.getUsername();
        String id = ipInfoDto.getId();
        List<IpDetailInfoDto> ipDetailInfoDtoListDto = ipInfoDto.getIpDetailInfoList();
        List<IpDetailInfoDto> ipDetailInfoDtoList = ipDetailInfoDtoListDto == null ? new ArrayList<>():ipDetailInfoDtoListDto;
        //是否填写过应用详情的分摊比例
        String hasWrited = "未填写";
        if(CollectionUtil.isNotEmpty(ipDetailInfoDtoList)){
            hasWrited = "已填写";
        }
        String changeType = "01";
        //新增
        if(StrUtil.isBlank(id)){
            IpInfo toSave = new IpInfo();
            BeanUtils.copyProperties(ipInfoDto,toSave);
            toSave.setOperator(username);
            toSave.setHasWrited(hasWrited);
            IpInfo saved = ipInfoRepo.save(toSave);
            List<IpDetailInfo> toSaveDetaillist = new ArrayList<>();
            for (IpDetailInfoDto dto : ipDetailInfoDtoList) {
                IpDetailInfo toSaveDetail = new IpDetailInfo();
                BeanUtils.copyProperties(dto,toSaveDetail);
                toSaveDetail.setOperator(username);
                toSaveDetail.setIpInfoId(saved.getId());
                toSaveDetail.setCreateTime(LocalDateTime.now());
                toSaveDetaillist.add(toSaveDetail);
            }
            if(!CollectionUtils.isEmpty(toSaveDetaillist)){
                ipDetailInfoRepo.saveAll(toSaveDetaillist);
            }
        }else{//编辑
            Long ipinfoId = Long.valueOf(id);
            ipInfoRepo.updateIpInfoId(ipinfoId,
                    ipInfoDto.getSourceType(),
                    ipInfoDto.getIp(),
                    LocalDateTime.now(),
                    ipInfoDto.getSystemUserName(),
                    ipInfoDto.getIpStatus(),
                    ipInfoDto.getSystemUserId(),
                    username,
                    ipInfoDto.getVirtualName(),
                    hasWrited);
            ipDetailInfoRepo.deleteAllByipInfoId(ipinfoId);
            List<IpDetailInfo> toSaveDetaillist = new ArrayList<>();
            for (IpDetailInfoDto dto : ipDetailInfoDtoList) {
                IpDetailInfo toSaveDetail = new IpDetailInfo();
                BeanUtils.copyProperties(dto,toSaveDetail);
                toSaveDetail.setId(null);
                toSaveDetail.setUpdateTime(null);
                toSaveDetail.setIpInfoId(ipinfoId);
                toSaveDetail.setOperator(username);
                toSaveDetaillist.add(toSaveDetail);
            }
            if(!CollectionUtils.isEmpty(toSaveDetaillist)){
                ipDetailInfoRepo.saveAll(toSaveDetaillist);
            }
            changeType = "02";
        }
        hisIpInfoService.saveHisIpInfo(ipInfoDto,username,changeType);
    }



    /**
     * 保存的检查
     * @param ipInfoDto
     */
    private void check4Save(IpInfoDto ipInfoDto) {
        String id = ipInfoDto.getId();
        //不允许新增重复
        if(StrUtil.isBlank(id)){
            IpInfo ipInfo = ipInfoRepo.queryByUniquekey(ipInfoDto.getUniqueKey());
            if(Objects.nonNull(ipInfo)){
                throw PlatformException.error("当前IP已添加，不允许重复添加。");
            }
        }

        //可添加若干根据id的所属关系校验
        List<IpDetailInfoDto> ipDetailInfoDtoList = ipInfoDto.getIpDetailInfoList();
        if(!CollectionUtils.isEmpty(ipDetailInfoDtoList)){
            BigDecimal reduce = ipDetailInfoDtoList.stream()
                    .filter(x -> Objects.nonNull(x.getSourceAllocation()))
                    .map(IpDetailInfoDto::getSourceAllocation)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            if (reduce.compareTo(new BigDecimal("100")) != 0) {
                throw PlatformException.error("成本分摊比例要求总和为100%");
            }
        }
    }

    public Page<IpInfo> findPage(IpInfoQueryDto ipInfoQueryDto) {
        logger.info("开始查询系统信息：{}", ipInfoQueryDto.toString());
        String pageSizeQuery = ipInfoQueryDto.getPageSize();
        String pageNoQuery = ipInfoQueryDto.getPageNo();
        Integer pageNo = Objects.nonNull(pageNoQuery) ? Integer.parseInt(pageNoQuery) : null;
        Integer pageSize = Objects.nonNull(pageSizeQuery) ? Integer.parseInt(pageSizeQuery) : null;
        pageNo = PageUtil.initPageNo(pageNo);
        pageSize = PageUtil.initPageSize(pageSize);
        Sort.Direction direction = Sort.Direction.DESC;
        String sort = "id";
        Pageable pageable = PageRequest.of(pageNo - 1, pageSize, direction, sort);
        List<IpInfo> resultList = queryIpInfoList(ipInfoQueryDto);
        List<IpInfo> resultListfilled =fillingName(resultList);
        //List<IpInfo> resultFilledWS = fillingWriteStatus(resultListfilled);
        return PageUtil.listConvertToPage(resultListfilled,pageable);
    }


    /**
     * 填充填写状态
     * @param resultListfilled
     * @return
     */
    private List<IpInfo> fillingWriteStatus(List<IpInfo> resultListfilled) {
        Map<Long, String> id2Uniquekey = resultListfilled.stream()
                .collect(Collectors.toMap(IpInfo::getId, IpInfo::getUniqueKey));
        Set<String> uinqueKeySet = resultListfilled.stream()
                .map(IpInfo::getUniqueKey).collect(Collectors.toSet());
        List<HisIpInfo> hisIpInfos = hisIpInfoRepo.queryByUniquekeys(uinqueKeySet);
        Map<String, List<HisIpInfo>> groupbyUnique = hisIpInfos.stream()
                .collect(Collectors.groupingBy(HisIpInfo::getUniqueKey));

        Set<Long> hisIPinfoIds = hisIpInfos.stream()
                .map(HisIpInfo::getId)
                .collect(Collectors.toSet());
        List<HisIpDetailInfo> detailInfos = hisIpDetailInfoRepo.queryByHisIpInfoIds(hisIPinfoIds);
        Set<Long> hasWritedIDs = detailInfos.stream()
                .map(HisIpDetailInfo::getIpInfoId)
                .collect(Collectors.toSet());
        for(IpInfo item : resultListfilled){
            Long id = item.getId();
            String uniqukey = id2Uniquekey.get(id);
            List<HisIpInfo> hisIpInfosByUnique = groupbyUnique.getOrDefault(uniqukey,new ArrayList<>());
            Set<Long> hisIdByUnqiue = hisIpInfosByUnique.stream()
                    .map(HisIpInfo::getId)
                    .collect(Collectors.toSet());
            Optional<Long> any = hisIdByUnqiue.stream()
                    .filter(hasWritedIDs::contains).findAny();
            if(any.isPresent()){
                item.setHasWrited("已填写");
            }else{
                item.setHasWrited("未填写");
            }
        }
        return resultListfilled;
    }

    /**
     * 填充系统和应用类别的名称
     * @param resultList
     * @return
     */
    private List<IpInfo> fillingName(List<IpInfo> resultList) {
        if(CollectionUtil.isEmpty(resultList)){
            return resultList;
        }
        Set<Long> componentCategoryIdSet = new HashSet<>();
        Set<String> systemClassNoSet = new HashSet<>();
        for(IpInfo temp : resultList){
            List<IpDetailInfo> ipDetailInfoList = temp.getIpDetailInfoList();
            Set<Long> componentCategoryIdSetTemp = ipDetailInfoList.stream()
                    .filter(x -> Objects.nonNull(x.getComponentCategoryId()))
                    .map(IpDetailInfo::getComponentCategoryId)
                    .collect(Collectors.toSet());
            componentCategoryIdSet.addAll(componentCategoryIdSetTemp);
            Set<String> systemClassNoSetTemp = ipDetailInfoList.stream()
                    .filter(x -> Objects.nonNull(x.getSystemClassNo()))
                    .map(IpDetailInfo::getSystemClassNo)
                    .collect(Collectors.toSet());
            systemClassNoSet.addAll(systemClassNoSetTemp);
        }
        Map<Long, String> id2Name = new HashMap<>();
        if(CollectionUtil.isNotEmpty(componentCategoryIdSet)){
            List<SystemComponentCategory> sccList = systemComponentCategoryRepo.queryByIdSet(componentCategoryIdSet);
            id2Name = sccList.stream().collect(Collectors.toMap(SystemComponentCategory::getId, SystemComponentCategory::getComponentCategory));
        }
        Map<String, String> systemClassNo2Name = new HashMap<>();
        if(CollectionUtil.isNotEmpty(systemClassNoSet)){
            List<BusiSystemInfo> busiSystemInfos = busiSystemInfoRepo.queryBySystemClassNo(systemClassNoSet);
             systemClassNo2Name = busiSystemInfos.stream().collect(Collectors.toMap(BusiSystemInfo::getSystemClassNo, BusiSystemInfo::getSystemName));
        }
        //避免JPA自动更新持久态对象
        for(IpInfo temp : resultList){
            List<IpDetailInfo> ipDetailInfoList = temp.getIpDetailInfoList();
            List<IpDetailInfo> toreturn = new ArrayList<>();
            for(IpDetailInfo ipTemp : ipDetailInfoList){
                IpDetailInfo ipDetailInfo = new IpDetailInfo();
                BeanUtils.copyProperties(ipTemp,ipDetailInfo);
                Long componentCategoryId = ipTemp.getComponentCategoryId();
                ipDetailInfo.setComponentCategory(id2Name.get(componentCategoryId));
                String systemClassNo = ipTemp.getSystemClassNo();
                ipDetailInfo.setSystemName(systemClassNo2Name.get(systemClassNo));
                toreturn.add(ipDetailInfo);
            }
            temp.setIpDetailInfoList(toreturn);
        }
        return resultList;
    }

    public List<IpInfo> queryIpInfoList(IpInfoQueryDto ipInfoQueryDto){
        Map<String, Object> param = new HashMap<>();
        PlatformUserDto user = userCache.get(request);
        Set<String> roleNames = new HashSet<>(user.getRoles());
        //个人数据 否则全部数据
        if (!"itadmin".equals(user.getUsername())
                && !roleNames.contains("itadmin")
                && !roleNames.contains(COSTALLOCATION_SYSTEMCOMPONENTDETAIL_ADMIN)){
            param.put("EQ_systemUserId",user.getUsername());
        }
        String ip = ipInfoQueryDto.getIp();
        if(StrUtil.isNotBlank(ip)){
            param.put("LIKE_ip",ip);
        }
        String hasWrited = ipInfoQueryDto.getHasWrited();
        if(StrUtil.isNotBlank(hasWrited)){
            param.put("EQ_hasWrited",hasWrited);
        }
        String ipStatus = ipInfoQueryDto.getIpStatus();
        if(StrUtil.isNotBlank(ipStatus)){
            param.put("EQ_ipStatus",ipStatus);
        }
        String sourceType = ipInfoQueryDto.getSourceType();
        if(StrUtil.isNotBlank(sourceType)){
            param.put("EQ_sourceType",sourceType);
        }
        Map<String, Object> paramIpDetail = new HashMap<>();
        String systemClass = ipInfoQueryDto.getSystemClass();
        if (StrUtil.isNotEmpty(systemClass)) {
            paramIpDetail.put("EQ_systemClass", systemClass);
        }
        String mainClass = ipInfoQueryDto.getMainClass();
        if (StrUtil.isNotEmpty(mainClass)) {
            paramIpDetail.put("EQ_mainClass", mainClass);
        }
        String systemClassNo = ipInfoQueryDto.getSystemClassNo();
        if (StrUtil.isNotEmpty(systemClassNo)) {
            paramIpDetail.put("EQ_systemClassNo", systemClassNo);
        }
        String exclusive = ipInfoQueryDto.getExclusive();
        if (StrUtil.isNotEmpty(exclusive)) {
            paramIpDetail.put("EQ_exclusive", exclusive);
        }
        String componentName = ipInfoQueryDto.getComponentName();
        if (StrUtil.isNotEmpty(componentName)) {
            paramIpDetail.put("LIKE_componentName", componentName);
        }
        String componentCategory = ipInfoQueryDto.getComponentCategory();
        if (StrUtil.isNotEmpty(componentCategory)) {
            paramIpDetail.put("EQ_componentCategory", componentCategory);
        }
        String componentCategoryId = ipInfoQueryDto.getComponentCategoryId();
        if (StrUtil.isNotEmpty(componentCategoryId)) {
            paramIpDetail.put("EQ_componentCategoryId", componentCategoryId);
        }
        String componentPath = ipInfoQueryDto.getComponentPath();
        if (StrUtil.isNotEmpty(componentPath)) {
            paramIpDetail.put("LIKE_componentPath", componentPath);
        }
        String runStatus = ipInfoQueryDto.getRunStatus();
        if (StrUtil.isNotEmpty(runStatus)) {
            paramIpDetail.put("EQ_runStatus", runStatus);
        }
        String mainOrBackup = ipInfoQueryDto.getMainOrBackup();
        if (StrUtil.isNotEmpty(mainOrBackup)) {
            paramIpDetail.put("EQ_mainOrBackup", mainOrBackup);
        }
        List<IpInfo> content = ipInfoRepo.findAll(SpecificationUtil.buildSpecification(param, IpInfo.class));
        List<IpInfo> resultList = new ArrayList<>();
        if(CollectionUtil.isNotEmpty(content)){
            Set<Long> collect = content.stream().map(IpInfo::getId).collect(Collectors.toSet());
            Map<Long, List<IpDetailInfo>> systemid2List = ipDetailInfoService.queryByIpInfoIdSet(collect,paramIpDetail);
            for (IpInfo temp : content) {
                List<IpDetailInfo> ipDetailInfoList = systemid2List.get(temp.getId());
                if(CollectionUtil.isNotEmpty(ipDetailInfoList)){
                    temp.setIpDetailInfoList(ipDetailInfoList);
                    resultList.add(temp);
                }else{
                    if (paramIpDetail.size() == 0) {
                        temp.setIpDetailInfoList(new ArrayList<>());
                        resultList.add(temp);
                    }
                }
            }
        }
        return resultList;
    }

    /**
     * 查询全部应用类别
     * @return
     */
    public Map<String, List<SystemComponentCategory>> getAllComponent() {
        Map<String, List<SystemComponentCategory>> result = new HashMap<>();
        List<SystemComponentCategory> temp = systemComponentCategoryRepo.findAll();

        List<BusiSystemInfo> all = busiSystemInfoRepo.findAll();
        if(CollectionUtil.isNotEmpty(all)){
            Map<String, List<BusiSystemInfo>> systemClassNo2BSI = all.stream()
                    .filter(x-> Objects.nonNull(x.getSystemClassNo()))
                    .collect(Collectors.groupingBy(BusiSystemInfo::getSystemClassNo));
            for (String systemClassNo : systemClassNo2BSI.keySet()) {
                List<BusiSystemInfo> busiSystemInfos = systemClassNo2BSI.get(systemClassNo);
                Set<Long> BUIids = busiSystemInfos.stream().map(BusiSystemInfo::getId).collect(Collectors.toSet());
                List<SystemComponentCategory> collect = temp.stream().filter(x -> BUIids.contains(x.getSystemInfoId())).collect(Collectors.toList());
                result.put(systemClassNo,collect);
            }
        }
        return result;
    }

    /**
     * 同步IP信息
     * 如果是新增，则在直接向base_ip表中插入数据，此时无流水
     * 如果是编辑，
     * @param newDto 待保存
     * @param oldDto 保存前数据
     * @param addORupdate 新增或者编辑 add / update
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void synchronizeBaseIpInfoAddOrUpdate(Object newDto,Object oldDto,String addORupdate) throws Exception {
        logger.info("开始新增编辑同步IP基础信息，待保存数据{}，保存前数据：{}", newDto,oldDto);
        if(newDto instanceof ItServerDevice){
            ItServerDevice itServerDeviceNew = (ItServerDevice) newDto;
            ItServerDevice itServerDeviceOld = (ItServerDevice) oldDto;
            this.syncItServerDevice(itServerDeviceNew,itServerDeviceOld,addORupdate);
        }else if(newDto instanceof ItCloudDevice){
            ItCloudDevice itCloudDeviceNew = (ItCloudDevice) newDto;
            ItCloudDevice itCloudDeviceOld = (ItCloudDevice) oldDto;
            this.syncItCloudDevice(itCloudDeviceNew,itCloudDeviceOld,addORupdate);
        }else if(newDto instanceof ItVirtualDevice){
            ItVirtualDevice itVirtualDeviceNew = (ItVirtualDevice) newDto;
            ItVirtualDevice itVirtualDeviceOld = (ItVirtualDevice) oldDto;
            this.syncItVirtualDevice(itVirtualDeviceNew,itVirtualDeviceOld,addORupdate);
        }else {
            logger.info("出错-开始新增编辑同步IP基础信息，待保存数据{}，保存前数据：{}", newDto,oldDto);
        }
    }

    public void syncItCloudDevice(ItCloudDevice itCloudDevice,ItCloudDevice oldITserver,String addORupdate){
        logger.info("开始同步ip信息，{},新增或编辑：{}", itCloudDevice.toString(),addORupdate);
        String devId = itCloudDevice.getDevId();
        if(Objects.isNull(devId)){
            //base_ip需要使用id作为唯一值
            return;
        }
        String newSystemClassNo = itCloudDevice.getBusinessName();
        //不同步 虚拟主机系统 动力环境系统
        if("34-0-012".equals(newSystemClassNo) || "33-0-014".equals(newSystemClassNo)){
            return;
        }
        PlatformUserDto user = userCache.get(request);
        String username = user.getUsername();
        //新增只考虑插入base_ip一条记录
        if("add".equals(addORupdate)){
            String ip1 = itCloudDevice.getInsideIp();
            if(StrUtil.isNotBlank(ip1)){
                String userId = itCloudDevice.getUserId();
                String oAaccountByUserId = getOAaccountByUserId(userId);
                IpInfo ipInfo = new IpInfo();
                ipInfo.setUniqueKey(devId);
                ipInfo.setIp(ip1);
                ipInfo.setSystemUserId(oAaccountByUserId);
                ipInfo.setSourceType("3");
                ipInfo.setOperator(username);
                ipInfo.setHasWrited("未填写");
                ipInfo.setIpStatus(null);
                ipInfoRepo.save(ipInfo);
                this.sendIpinfoAddWChat(oAaccountByUserId,ip1);
            }
        }
        //
        if("update".equals(addORupdate)){
            //已落库内容
            String oldIP1 = oldITserver.getInsideIp();
            String oldUserId = oldITserver.getUserId();
            //本次请求的参数
            String newIP1 = itCloudDevice.getInsideIp();
            String newUserId = itCloudDevice.getUserId();
            String oAaccountByUserId = getOAaccountByUserId(newUserId);
            String oAaccountByUserIdOld = getOAaccountByUserId(oldUserId);
            if(Objects.equals(oldIP1,newIP1)){
                if(StrUtil.isBlank(oldIP1)){
                    return;
                }
                //ip相同 责任人不同
                if(!Objects.equals(oldUserId,newUserId)){
                    updateBaseIpAndIpinfo(devId,oAaccountByUserId,oAaccountByUserIdOld,null,null);
                }
            }else{//ip不相等
                //责任人不变
                if(Objects.equals(oldUserId,newUserId)){
                    updateBaseIpAndIpinfoWithIP(devId, newIP1, oAaccountByUserId,null,
                            oldIP1,oAaccountByUserId);
                }else{ //ip不相等 责任人变
                    doOnlineIPWithIPDetail(devId,newIP1,null,
                            oAaccountByUserId,"3",null,
                            oldIP1,oAaccountByUserIdOld);
                }
            }
        }
    }

    /**
     * ip发生变化 责任人不变
     * @param uniqueKey
     * @param newIP
     */
    public void updateBaseIpAndIpinfoWithIP(String uniqueKey, String newIP,
                                            String newUserOAaccount,String virtualName,
                                            String oldIp,String oldUserOAccount){
        logger.info("开始baseIp和应用详情的同步操作:{},责任人：{},新IP：{}",
                uniqueKey,newUserOAaccount,newIP);
        PlatformUserDto user = userCache.get(request);
        String username = user.getUsername();
        //1 baseIp表
        if(StrUtil.isNotBlank(newIP)){
            //2应用详情
            IpInfo ipInfo = ipInfoRepo.queryByUniquekey(uniqueKey);
            logger.info("查询IPinfo结果：{}",Objects.nonNull(ipInfo));
            if (Objects.nonNull(ipInfo)) {
                //非首次-更新
                ipInfo.setIp(newIP);
                ipInfo.setVirtualName(virtualName);
                ipInfo.setUpdateTime(LocalDateTime.now());
                ipInfo.setSystemUserId(newUserOAaccount);
                ipInfo.setOperator(username);
                ipInfoRepo.save(ipInfo);
                //3保存历史
                hisIpInfoService.saveHisIpInfoFromSync(ipInfo,username,"02");
            }else{
                //首次-新增
                IpInfo toSave = new IpInfo();
                toSave.setUniqueKey(uniqueKey);
                toSave.setIp(newIP);
                toSave.setSystemUserId(newUserOAaccount);
                toSave.setSourceType("3");
                toSave.setOperator(username);
                toSave.setIpStatus(null);
                toSave.setHasWrited("未填写");
                ipInfoRepo.save(toSave);
                this.sendIpinfoAddWChat(newUserOAaccount,newIP);

            }
            //4发送消息
            sendIpinfoUpdateWChat(newUserOAaccount,newIP,oldUserOAccount,oldIp);
        }
    }


    public void syncItVirtualDevice(ItVirtualDevice itVirtualDevice,ItVirtualDevice oldITserver,String addORupdate){
        logger.info("开始同步ip信息，{},新增或编辑：{}", itVirtualDevice.toString(),addORupdate);
        String uniqueKey = itVirtualDevice.getDevId();
        if(Objects.isNull(uniqueKey)){
            //base_ip需要使用id作为唯一值
            return;
        }
        String newSystemClassNo = itVirtualDevice.getBusinessName();
        //不同步 虚拟主机系统 动力环境系统
        if("34-0-012".equals(newSystemClassNo) || "33-0-014".equals(newSystemClassNo)){
            return;
        }
        String virtualName = itVirtualDevice.getVirtualName();
        PlatformUserDto user = userCache.get(request);
        String username = user.getUsername();
        //新增只考虑插入base_ip一条记录
        if("add".equals(addORupdate)){
            String ip1 = itVirtualDevice.getIp1();
            if(StrUtil.isNotBlank(ip1)){
                String userId = itVirtualDevice.getUserId();
                String oAaccountByUserId = getOAaccountByUserId(userId);
                IpInfo ipInfo = new IpInfo();
                ipInfo.setVirtualName(virtualName);
                ipInfo.setUniqueKey(uniqueKey);
                ipInfo.setIp(ip1);
                ipInfo.setSystemUserId(oAaccountByUserId);
                ipInfo.setSourceType("2");
                ipInfo.setOperator(username);
                ipInfo.setIpStatus(null);
                ipInfo.setHasWrited("未填写");
                ipInfoRepo.save(ipInfo);
                this.sendIpinfoAddWChat(oAaccountByUserId,ip1);
            }
        }
        if("update".equals(addORupdate)){
            //已落库内容
            String oldIP1 = oldITserver.getIp1();
            String oldUserId = oldITserver.getUserId();
            //本次请求的参数
            String newIP1 = itVirtualDevice.getIp1();
            String newUserId = itVirtualDevice.getUserId();
            String oAaccountByUserId = getOAaccountByUserId(newUserId);
            String oAaccountByUserIdOld = getOAaccountByUserId(oldUserId);
            if(Objects.equals(oldIP1,newIP1)){
                if(StrUtil.isBlank(oldIP1)){
                    return;
                }
                //ip相同 责任人不同
                if(!Objects.equals(oldUserId,newUserId)){
                    updateBaseIpAndIpinfo(uniqueKey,oAaccountByUserId,oAaccountByUserIdOld,virtualName,null);
                }
            }else{//ip不相等
                //责任人不变
                if(Objects.equals(oldUserId,newUserId)){
                    updateBaseIpAndIpinfoWithIP(uniqueKey, newIP1,
                            oAaccountByUserId,virtualName,
                            oldIP1,oAaccountByUserId);
                }else{ //ip不相等 责任人变
                    doOnlineIPWithIPDetail(uniqueKey,newIP1,null,
                            oAaccountByUserId,"2",virtualName,
                            oldIP1,oAaccountByUserIdOld);
                }
            }
        }
    }


    public void syncItServerDevice(ItServerDevice itServerDevice,ItServerDevice oldITserver,String addORupdate){
        logger.info("开始同步ip信息，{},新增或编辑：{}", itServerDevice.toString(),addORupdate);
        Integer devId = itServerDevice.getDevId();
        if(Objects.isNull(devId)){
            //base_ip需要使用id作为唯一值
            return;
        }
        String newSystemClassNo = itServerDevice.getBusinessName();
        //不同步 虚拟主机系统 动力环境系统
        if("34-0-012".equals(newSystemClassNo) || "33-0-014".equals(newSystemClassNo)){
            return;
        }
        PlatformUserDto user = userCache.get(request);
        String username = user.getUsername();
        String uniqueKey = String.valueOf(devId);
        //新增只考虑插入base_ip一条记录
        if("add".equals(addORupdate)){
            String ip1 = itServerDevice.getIp1();
            if(StrUtil.isNotBlank(ip1)){
                String machineStatus = itServerDevice.getMachineStatus();
                String userId = itServerDevice.getUserId();
                String oAaccountByUserId = getOAaccountByUserId(userId);
                //只有这三种状态认为是新增
                if(StrUtil.isBlank(machineStatus)
                        || "15".equals(machineStatus)
                        || "18".equals(machineStatus)){
                    IpInfo ipInfo = new IpInfo();
                    ipInfo.setUniqueKey(uniqueKey);
                    ipInfo.setIp(ip1);
                    ipInfo.setSystemUserId(oAaccountByUserId);
                    ipInfo.setSourceType("1");
                    ipInfo.setOperator(username);
                    ipInfo.setIpStatus(machineStatus);
                    ipInfo.setHasWrited("未填写");
                    ipInfoRepo.save(ipInfo);
                    this.sendIpinfoAddWChat(oAaccountByUserId,ip1);
                }
                //新增即时下架
                if ("116".equals(machineStatus)) {
                    //首次新增 it资产的主键是第一次生成 ，此时base_ip中没有对应值
                    //不做处理
                }
            }
        }
        //
        if("update".equals(addORupdate)){
            //已落库内容
            String oldIP1 = oldITserver.getIp1();
            String oldMachineStatus = oldITserver.getMachineStatus();
            String oldUserId = oldITserver.getUserId();
            //本次请求的参数
            String newIP1 = itServerDevice.getIp1();
            String newMachineStatus = itServerDevice.getMachineStatus();
            String newUserId = itServerDevice.getUserId();
            String oAaccountByUserId = getOAaccountByUserId(newUserId);
            String oAaccountByUserIdOld = getOAaccountByUserId(oldUserId);
            String oldMS = onlineOrOffline(oldMachineStatus);
            String newMS = onlineOrOffline(newMachineStatus);
            if(Objects.equals(oldIP1,newIP1)){
                if(StrUtil.isBlank(oldIP1)){
                    return;
                }
                if(Objects.equals(oldUserId,newUserId)){//ip相同 责任人相同
                    //只处理状态变化
                    if(!Objects.equals(oldMachineStatus,newMachineStatus)){
                        //非下架 -》 下架
                        if(!"offline".equals(oldMS) && "offline".equals(newMS)){
                            doOfflineIP(uniqueKey);
                        }
                        //非上架 -》 上架
                        if(!"online".equals(oldMS) && "online".equals(newMS)){
                            doOnlineIP(uniqueKey,newIP1,newMachineStatus,oAaccountByUserId,oldIP1,oAaccountByUserIdOld);
                        }
                    }
                }else{//ip相同 责任人不同
                    //状态不变
                    if("online".equals(newMS) && "online".equals(oldMS)){
                        updateBaseIpAndIpinfo(uniqueKey,oAaccountByUserId,oAaccountByUserIdOld,null,newMachineStatus);
                    }
                }
            }else{//ip不相等
                //责任人不变
                if(Objects.equals(oldUserId,newUserId)){
                    //状态不变
                    if(Objects.equals(oldMachineStatus,newMachineStatus)){
                        if("online".equals(newMS)){
                            doOnlineIPWithIPDetail(uniqueKey,newIP1,newMachineStatus,
                                    oAaccountByUserId,"1",null,
                                    oldIP1,oAaccountByUserId);
                        }
                    }else{//状态变
                        //非下架 -》 下架
                        if(!"offline".equals(oldMS) && "offline".equals(newMS)){
                            doOfflineIP(uniqueKey);
                        }
                        //非上架 -》 上架
                        if(!"online".equals(oldMS) && "online".equals(newMS)){
                            doOnlineIP(uniqueKey,newIP1,newMachineStatus,oAaccountByUserId,oldIP1,oAaccountByUserIdOld);
                        }
                    }
                }else{ //ip不相等 责任人变
                    // ip不相等 责任人变 状态不变
                    if(Objects.equals(oldMachineStatus,newMachineStatus)){
                        if("online".equals(newMS)){
                            doOnlineIPWithIPDetail(uniqueKey,newIP1,
                                    newMachineStatus,oAaccountByUserId,
                                    "1",null,
                                    oldIP1,oAaccountByUserIdOld);
                        }
                    }else{// ip不相等 责任人变 状态变化
                        //非上架 -》 上架
                        if(!"online".equals(oldMS) && "online".equals(newMS)){
                            doOnlineIP(uniqueKey,newIP1,newMachineStatus,oAaccountByUserId,oldIP1,oAaccountByUserIdOld);
                        }
                    }
                }
            }
        }
    }

    /**
     * 1）IP 状态 不变 2）责任人变化 3）上架状态
     * 更新1 baseIp表 2应用详情3保存历史4发消息
     *
     *
     * @param uniqueKey
     * @param newUserOAaccount
     */
    public void updateBaseIpAndIpinfo(String uniqueKey, String newUserOAaccount,String oldUserOAaccount,String virtualName,String newMS){
        logger.info("开始baseIp和应用详情的同步操作:{},责任人：{},虚拟机名称：{}",
                uniqueKey,newUserOAaccount,virtualName);
        PlatformUserDto user = userCache.get(request);
        String username = user.getUsername();
        //1 baseIp表
        if(StrUtil.isBlank(newUserOAaccount)){
            doOfflineIP(uniqueKey);
        }else{
            //2应用详情
            String ip = "";
            IpInfo ipInfo = ipInfoRepo.queryByUniquekey(uniqueKey);
            if (Objects.nonNull(ipInfo)) {
                ip = ipInfo.getIp();
                ipInfo.setSystemUserId(newUserOAaccount);
                ipInfo.setIpStatus(newMS);
                ipInfo.setUpdateTime(LocalDateTime.now());
                ipInfoRepo.save(ipInfo);
                //3保存历史
                hisIpInfoService.saveHisIpInfoFromSync(ipInfo,username,"02");
            }
            //4发送消息
            if (StrUtil.isNotBlank(ip)) {
                sendIpinfoUpdateWChat(newUserOAaccount,ip,oldUserOAaccount,ip);
            }
        }
    }

    /**
     * 非上架 -》 上架
     * 应用详情中未使用
     * @param uniqueKey
     * @param newIP1
     * @param newMS
     * @param newUserOAaccount
     */
    private void doOnlineIPWithIPDetail(String uniqueKey, String newIP1,
                                        String newMS, String newUserOAaccount,
                                        String sourceType,String virtualName,
                                        String oldIp,String oldUserOaccount) {
        PlatformUserDto user = userCache.get(request);
        String username = user.getUsername();
        logger.info("开始资产下架的同步操作:{},操作人：{}",uniqueKey,username);

        if(StrUtil.isBlank(uniqueKey) ||StrUtil.isBlank(newIP1)){
            return;
        }
        //2应用详情
        IpInfo ipInfo = ipInfoRepo.queryByUniquekey(uniqueKey);
        if (Objects.nonNull(ipInfo)) {
            ipInfo.setIp(newIP1);
            ipInfo.setSystemUserId(newUserOAaccount);
            ipInfo.setUpdateTime(LocalDateTime.now());
            ipInfoRepo.save(ipInfo);
            //3保存历史
            hisIpInfoService.saveHisIpInfoFromSync(ipInfo,username,"02");
        }else{
            //新增操作
            IpInfo toSave = new IpInfo();
            toSave.setIpStatus(newMS);
            toSave.setIp(newIP1);
            toSave.setVirtualName(virtualName);
            toSave.setSourceType(sourceType);
            toSave.setUniqueKey(uniqueKey);
            toSave.setSystemUserId(newUserOAaccount);
            toSave.setOperator(username);
            toSave.setHasWrited("未填写");
            ipInfoRepo.save(toSave);
        }
        //4发送消息
        sendIpinfoUpdateWChat(newUserOAaccount,newIP1,oldUserOaccount,oldIp);
    }


    /**
     * 非上架 -》 上架
     * 应用详情中未使用
     * @param uniqueKey
     * @param newIP1
     * @param newMS
     * @param newUserOAaccount
     */
    private void doOnlineIP(String uniqueKey, String newIP1,
                            String newMS, String newUserOAaccount,
                            String oldIp,String oldUserOaccount) {
        PlatformUserDto user = userCache.get(request);
        String username = user.getUsername();
        logger.info("开始资产下架的同步操作:{},操作人：{}",uniqueKey,username);

        if(StrUtil.isBlank(uniqueKey)){
            return;
        }
        IpInfo baseIpInfo = ipInfoRepo.queryByUniquekey(uniqueKey);
        if (Objects.isNull(baseIpInfo)) {//新增
            IpInfo toSave = new IpInfo();
            toSave.setIpStatus(newMS);
            toSave.setIp(newIP1);
            toSave.setSourceType("1");
            toSave.setUniqueKey(uniqueKey);
            toSave.setSystemUserId(newUserOAaccount);
            toSave.setOperator(username);
            toSave.setHasWrited("未填写");
            ipInfoRepo.save(toSave);
        }else{//更新操作
            baseIpInfo.setIpStatus(newMS);
            baseIpInfo.setIp(newIP1);
            baseIpInfo.setSourceType("1");
            baseIpInfo.setUniqueKey(uniqueKey);
            baseIpInfo.setSystemUserId(newUserOAaccount);
            baseIpInfo.setUpdateTime(LocalDateTime.now());
            baseIpInfo.setOperator(username);
            ipInfoRepo.save(baseIpInfo);
        }
        sendIpinfoUpdateWChat(newUserOAaccount,newIP1,oldUserOaccount,oldIp);
    }


    /**
     * 某一台资产下架
     * 1 移除baseip信息
     * 2 移除应用详情内容
     * 3 添加应用详情历史
     * 4 给责任人发消息 【如果有】
     * @param uniqueKey
     */
    @Transactional
    public void doOfflineIP(String uniqueKey){
        PlatformUserDto user = userCache.get(request);
        String username = user.getUsername();
        logger.info("开始资产下架的同步操作:{},操作人：{}",uniqueKey,username);

        if(StrUtil.isBlank(uniqueKey)){
            return;
        }
        String systemUserId = "";
        String ip = "";

        IpInfo ipInfo = ipInfoRepo.queryByUniquekey(uniqueKey);
        //有些ip新建之后 没有分配比例 后直接删除 此时ip_info中没有记录
        if(Objects.nonNull(ipInfo)){
            ip = ipInfo.getIp();
            systemUserId = ipInfo.getSystemUserId();
            hisIpInfoService.saveHisIpInfoFromSync(ipInfo,username,"03");
            ipInfoRepo.deleteByUniquekey(uniqueKey);
        }
        this.sendDeleteWChat(systemUserId, ip);
    }

    /**
     * 判断服务器状态
     * @param machineStatus
     * @return
     */
    public String onlineOrOffline(String machineStatus){
        logger.info("判断服务器状态：{}", machineStatus);
        if(StrUtil.isBlank(machineStatus)
                || "15".equals(machineStatus)
                || "18".equals(machineStatus)){
            return "online";
        }
        if("116".equals(machineStatus)){
            return "offline";
        }
        return "other";
    }

    public void sendIpinfoAddWChat(String userName, String newIP) {
        logger.info("新增应用详情-发送责任人消息：{}，ip名称：{}", userName, newIP);
        if (StrUtil.isBlank(userName)) {
            return;
        }
       List<String> toSend = new ArrayList<>();
        toSend.add(userName);
        SystemConfig agentIdConfig = configService.findByCode("WECHAT_GATEWAY_APP_AGENTID");
        MessageGenericVo build = MessageGenericVo.builder()
                .oaUserAccounts(toSend)
                .agentId(agentIdConfig.getConfigValue())
                .textContent("新增-IP：" + newIP + "，请维护成本分摊管理菜单的相关数据")
                .build();
        String msg = shortmsgService.sendAgentMessageGeneric(build);
        logger.info("新增应用详情-完成发送责任人消息：{}", msg);
    }

    public void sendIpinfoUpdateWChat(String newUserName, String newIP,String oldUserName,String oldIp) {
        logger.info("更新应用详情-发送新责任人：{},新IP：{}，旧责任人：{},旧IP：{}", newUserName, newIP,oldUserName,oldIp);
        if (StrUtil.isBlank(newUserName)) {
            return;
        }
        List<String> toSend = new ArrayList<>();
        toSend.add(newUserName);
        SystemConfig agentIdConfig = configService.findByCode("WECHAT_GATEWAY_APP_AGENTID");
        MessageGenericVo build = MessageGenericVo.builder()
                .oaUserAccounts(toSend)
                .agentId(agentIdConfig.getConfigValue())
                .textContent("变更-新责任人："+newUserName +
                        ",新IP：" + newIP +
                        "，旧责任人：" + oldUserName+
                        ",旧IP：" + oldIp
                        + "，请维护成本分摊管理菜单的相关数据")
                .build();
        String msg = shortmsgService.sendAgentMessageGeneric(build);
        logger.info("更新应用详情-完成发送责任人消息：{}", msg);
    }


    /**
     * 给责任人发送 新增/删除 IP企微消息
     *
     * @param userName
     * @param newIP
     */
    public void sendDeleteWChat(String userName, String newIP) {
        logger.info("发送责任人消息：{}，ip名称：{}", userName, newIP);
        if (StrUtil.isBlank(userName)) {
            return;
        }
       List<String> toSend = new ArrayList<>();
        toSend.add(userName);
        SystemConfig agentIdConfig = configService.findByCode("WECHAT_GATEWAY_APP_AGENTID");
        MessageGenericVo build = MessageGenericVo.builder()
                .oaUserAccounts(toSend)
                .agentId(agentIdConfig.getConfigValue())
                .textContent("删除-IP：" + newIP + "，请维护成本分摊管理菜单的相关数据")
                .build();
        String msg = shortmsgService.sendAgentMessageGeneric(build);
        logger.info("完成发送责任人消息：{}", msg);
    }


    /**
     * 根据userId查询oa账号
     * 3456 -> guoj
     * @param userId
     * @return
     */
    public String getOAaccountByUserId(String userId){
        String OAAccount = "";
        if(StrUtil.isNotBlank(userId)){
            List<Integer> userIds = new ArrayList<>();
            userIds.add(Integer.valueOf(userId));
            LdapResponse<List<LdapEhrEmpDto>> userList = feignLdapService.getByOaUserIdList(userIds);
            List<LdapEhrEmpDto> data = userList.getData();
            LdapEhrEmpDto ldapEhrEmpDto = data.get(0);
            OAAccount = ldapEhrEmpDto.getBadge();
        }
        return OAAccount;
    }

    /**
     * 获取使用指定业务系统的全部应用详情的责任人
     * @param systemClassNo
     * @return
     */
    public List<String> getAllOAAccountBySystemNo(String systemClassNo){
        if (StrUtil.isBlank(systemClassNo)) {
            return new ArrayList<>();
        }
        List<IpDetailInfo> ipDetailInfoList = ipDetailInfoRepo.queryBySystemClassNo(systemClassNo);
        Set<Long> ipInfoIds = ipDetailInfoList.stream()
                .map(IpDetailInfo::getIpInfoId).collect(Collectors.toSet());
        List<IpInfo> ipInfoList = ipInfoRepo.queryByIDS(ipInfoIds);
        Set<String> collect = ipInfoList.stream()
                .filter(x -> StrUtil.isNotBlank(x.getSystemUserId()))
                .map(IpInfo::getSystemUserId)
                .collect(Collectors.toSet());
        return new ArrayList<>(collect);
    }

    /**
     * 查询导出数据
     * @param ipInfoQueryDto
     * @return
     */
    public List<IpInfoDetailExportDto> queryExportData(IpInfoQueryDto ipInfoQueryDto) {
        logger.info("开始查询应用详情待导出信息：{}", ipInfoQueryDto.toString());
        List<IpInfo> resultList = queryIpInfoList(ipInfoQueryDto);
        List<IpInfo> resultListfilled =fillingName(resultList);
        List<IpInfoDetailExportDto> result = new ArrayList<>();
        for(IpInfo item : resultListfilled){
            String uniqueKey = item.getUniqueKey();
            String ip = item.getIp();
            String virtualName = item.getVirtualName();
            List<IpDetailInfo> ipDetailInfoList = item.getIpDetailInfoList();
            if (CollectionUtil.isNotEmpty(ipDetailInfoList)) {
                for(IpDetailInfo detailItem : ipDetailInfoList){
                    IpInfoDetailExportDto toReturn = new IpInfoDetailExportDto();
                    toReturn.setUniqueKey(uniqueKey);
                    toReturn.setIp(ip);
                    toReturn.setVirtualName(virtualName);
                    toReturn.setComponentCategory(detailItem.getComponentCategory());
                    toReturn.setExclusive(detailItem.getExclusive());
                    toReturn.setComponentName(detailItem.getComponentName());
                    toReturn.setSystemName(detailItem.getSystemName());
                    toReturn.setComponentPath(detailItem.getComponentPath());
                    toReturn.setMainOrBackup(detailItem.getMainOrBackup());
                    toReturn.setRunStatus(detailItem.getRunStatus());
                    toReturn.setSourceAllocation(detailItem.getSourceAllocation().toPlainString());
                    result.add(toReturn);
                }
            }else{
                IpInfoDetailExportDto toReturn = new IpInfoDetailExportDto();
                toReturn.setUniqueKey(uniqueKey);
                toReturn.setIp(ip);
                toReturn.setVirtualName(virtualName);
                result.add(toReturn);
            }
        }
        return result;
    }


    /**
     * 导入应用详情数据
     * @param file
     * @return
     */
    public ReportUploadContext<UploadIpInfoDetailDto, String> uploadUploadIpInfoDetail(MultipartFile file) throws IOException {
        ReportUploadContext<UploadIpInfoDetailDto, String> context = ReportUploadContext.<UploadIpInfoDetailDto, String>builder()
                .config(ReportFileConfigEnum.UPLOAD_IPINFO_DETAIL)
                .file(file)
                .build();
        ReportFileUtil.readSingleExcel(context);
        AssertOverride.notEmpty(context.getReadRes(), "上传内容不可为空");

        List<UploadIpInfoDetailDto> readResList = context.getReadRes();
        //后期数据量大 考虑异步执行
        if(!checkUploadIpinfoData(readResList)){
            context.setCheckPass(false);
            return context;
        }
        return context;
    }
    public boolean checkUploadIpinfoData(List<UploadIpInfoDetailDto> readResList){
        //必填项
        Optional<UploadIpInfoDetailDto> any = readResList.stream().filter(x -> StrUtil.isBlank(x.getUniqueKey())
                || StrUtil.isBlank(x.getIp())
                || StrUtil.isBlank(x.getComponentCategory())
                || StrUtil.isBlank(x.getComponentName())
                || StrUtil.isBlank(x.getExclusive())
                || StrUtil.isBlank(x.getRunStatus())
                || StrUtil.isBlank(x.getMainOrBackup())
                || StrUtil.isBlank(x.getComponentPath())
                || StrUtil.isBlank(x.getSourceAllocation())
                //100 但是非独占
                || (x.getSourceAllocation().startsWith("100") && Objects.equals("N",x.getExclusive()))
                || StrUtil.isBlank(x.getSystemName())).findAny();
        if(any.isPresent()){
            logger.info("必填项不符合：{}",any.get().getUniqueKey());
            return false;
        }

        Map<String, List<UploadIpInfoDetailDto>> uniqueKey2List = readResList.stream()
                .collect(Collectors.groupingBy(UploadIpInfoDetailDto::getUniqueKey));
        Set<String> strings = uniqueKey2List.keySet();
        PlatformUserDto user = userCache.get(request);
        String username = user.getUsername();
        List<IpInfo> ipInfoList = ipInfoRepo.queryByUniquekeySet(strings);
        Set<String> userOaSet = ipInfoList.stream().map(IpInfo::getSystemUserId)
                .collect(Collectors.toSet());
        //全部资产的责任人只有一个  且等于 当前用户
        boolean auth = userOaSet.size() ==1 && userOaSet.contains(username);
        if(!auth){
            return false;
        }

        List<BusiSystemInfo> busiAll = busiSystemInfoRepo.findAll();
        Map<String, BusiSystemInfo> systemName2Object = busiAll.stream()
                .filter(x-> StrUtil.isNotBlank(x.getSystemName()))
                .collect(Collectors.toMap(BusiSystemInfo::getSystemName, x -> x));
        Optional<UploadIpInfoDetailDto> checkSystemName = readResList.stream()
                .filter(x -> !systemName2Object.keySet().contains(x.getSystemName()))
                .findAny();
        if (checkSystemName.isPresent()) {
            logger.info("系统名称必须存在于系统信息中：{}", checkSystemName.get().getSystemName());
            return false;
        }


        Map<String, List<UploadIpInfoDetailDto>> systemName2List = readResList.stream()
                .collect(Collectors.groupingBy(UploadIpInfoDetailDto::getSystemName));
        List<SystemComponentCategory> allComponent = systemComponentCategoryRepo.findAll();
        Map<Long, List<SystemComponentCategory>> sysId2List = allComponent.stream()
                .collect(Collectors.groupingBy(SystemComponentCategory::getSystemInfoId));
        Map<String, Long> sysName2SystemID = busiAll.stream()
                .filter(x-> StrUtil.isNotBlank(x.getSystemName()))
                .collect(Collectors.toMap(BusiSystemInfo::getSystemName, BusiSystemInfo::getId));
        for (String systemName : systemName2List.keySet()) {
            Long aLong = sysName2SystemID.get(systemName);
            List<SystemComponentCategory> systemComponentCategoryList = sysId2List.get(aLong);
            //已落库的 当前系统信息对应的应用类别
            Set<String> comSet = systemComponentCategoryList.stream()
                    .map(SystemComponentCategory::getComponentCategory)
                    .collect(Collectors.toSet());
            List<UploadIpInfoDetailDto> uploadIpInfoDetailDtos = systemName2List.get(systemName);
            Optional<UploadIpInfoDetailDto> any1 = uploadIpInfoDetailDtos.stream()
                    .filter(x -> !comSet.contains(x.getComponentCategory()))
                    .findAny();
            if (any1.isPresent()) {
                logger.info("校验系统信息和应用类别的关系：{}-{}", systemName, any1.get().getComponentCategory());
                return false;
            }
        }
        try {
            saveIpInfo(uniqueKey2List,ipInfoList,systemName2Object,sysId2List);
        } catch (Exception e) {
            logger.info("导入失败");
            return false;
        }
        return true;
    }

    @Transactional
    public  void saveIpInfo(Map<String, List<UploadIpInfoDetailDto>> uniqueKey2List,
                            List<IpInfo> ipInfoList,Map<String, BusiSystemInfo> systemName2Object,
                            Map<Long, List<SystemComponentCategory>> sysId2List) {
        //此处应该
        Map<String, IpInfo> uniq2Object = ipInfoList.stream()
                .collect(Collectors.toMap(IpInfo::getUniqueKey,x->x));
        for (String uniquekey : uniqueKey2List.keySet()) {
            IpInfoDto ipInfoDto = new IpInfoDto();
            IpInfo ipInfo = uniq2Object.get(uniquekey);
            BeanUtils.copyProperties(ipInfo,ipInfoDto);
            ipInfoDto.setId(ipInfo.getId().toString());
            List<UploadIpInfoDetailDto> uploadIpInfoDetailDtos = uniqueKey2List.get(uniquekey);
            List<IpDetailInfoDto> toSet = new ArrayList<>();
            for(UploadIpInfoDetailDto item : uploadIpInfoDetailDtos){
                IpDetailInfoDto ipDetailInfo = new IpDetailInfoDto();
                BeanUtils.copyProperties(item,ipDetailInfo);
                Long ipInfoId = ipInfo.getId();
                ipDetailInfo.setIpInfoId(ipInfoId);
                ipDetailInfo.setSourceAllocation(new BigDecimal(item.getSourceAllocation()));
                BusiSystemInfo busiSystemInfo = systemName2Object.get(item.getSystemName());
                ipDetailInfo.setSystemClass(busiSystemInfo.getSystemClass());
                ipDetailInfo.setSystemClassNo(busiSystemInfo.getSystemClassNo());
                ipDetailInfo.setMainClass(busiSystemInfo.getMainClass());
                String componentCategory = item.getComponentCategory();
                List<SystemComponentCategory> systemComponentCategoryList = sysId2List.get(busiSystemInfo.getId());
                Optional<SystemComponentCategory> first = systemComponentCategoryList.stream()
                        .filter(x -> Objects.equals(componentCategory, x.getComponentCategory()))
                        .findFirst();
                if (first.isPresent()) {
                    ipDetailInfo.setComponentCategoryId(first.get().getId());
                }else {
                    logger.info("找不到应用类别的主键，{}-{}-{}", uniquekey, ipInfoId, componentCategory);
                    throw PlatformException.error("找不到应用类别的主键");
                }
                toSet.add(ipDetailInfo);
            }
            ipInfoDto.setIpDetailInfoList(toSet);
            saveOrUpdateCurrAndHistory(ipInfoDto);
        }
    }
}
